import { tmCv } from '.'
import { color } from './color'
import { shapeStyle } from './interface'
import { division, addition, multiply, subtract, uuid } from './util'

export class Shape {
  id: string = uuid(16)

  x = 0
  y = 0
  width = 0
  height = 0
  fillStyle = 'rgba(0,0,0,0)'
  strokeStyle = 'rgba(0,0,0,0)'
  lineWidth = 0
  lineDashOffset = 0
  lineDash: number[] = [0]
  sAngle = 0
  eAngle = 0
  radius: [number, number, number, number] = [0, 0, 0, 0]
  /**一些圆弧等用到的内半径 */
  r = 0
  /**圆环时可能用到的内半径 */
  innerRadius = 0
  lineCap: any = 'round'
  lineJoin: any = 'round'
  textMaxWidth = 0
  /** 字符间距不支持断行 */
  letterSpace = 0
  text = ''
  playing = false
  fontSize = 14
  textAlign: 'left' | 'right' | 'center' = 'left'

  canvas: tmCv
  constructor(tmcv: tmCv, arg: Partial<shapeStyle>) {
    for (const item in arg) {
      // @ts-expect-error
      this[item] = arg[item]
      // @ts-expect-error
      this['back_' + item] = arg[item]
    }
    this.canvas = tmcv
    this.draw()
  }
  /**绘制 */
  draw<T>(arg?: shapeStyle) {
    return this
  }
  /**动画 */
  public animate(
    arg: Partial<shapeStyle>,
    animateConfig?: {
      /**动画时长 */
      duration?: number
      /**重复次数 */
      repeat?: number
      /**是否来回动画0-1，1-0这样的过渡效果 */
      yoyo?: boolean
    }
  ) {
    const config = {
      duration: 500,
      repeat: 0,
      yoyo: false,
      onStart: () => {},
      ...(animateConfig || {}),
    }
    this.playing = true

    return this.canvas
      .animation(config, (progress: number) => {
        // 计算动画过程中矩形的位置和颜色
        let { x, y, width, height, radius, eAngle, sAngle, textMaxWidth, letterSpace, fontSize } = this
        if (typeof arg.x !== 'undefined') {
          const baseX = this['back_x'] ?? 0
          x = baseX + Number(arg.x - baseX) * progress
        }
        if (typeof arg.y !== 'undefined') {
          const baseY = this['back_y'] ?? 0
          y = baseY + Number(arg.y - baseY) * progress
        }
        if (typeof arg.width !== 'undefined') {
          const baseWidth = this['back_width'] ?? 0
          width = baseWidth + Math.abs((arg.width - baseWidth) * progress)
        }
        if (typeof arg.width !== 'undefined') {
          const baseHeight = this['back_height'] ?? 0
          height = baseHeight + Math.abs((arg.height - baseHeight) * progress)
        }
        if (typeof arg.radius !== 'undefined' && radius) {
          this.radius = multiply(arg.radius, progress)
        }
        if (typeof arg.eAngle !== 'undefined' && eAngle) {
          this.eAngle = Number(arg.eAngle) * progress
        }
        if (typeof arg.sAngle !== 'undefined' && sAngle) {
          this.sAngle = Number(arg.sAngle) * progress
        }
        if (typeof arg?.textMaxWidth !== 'undefined') {
          this.textMaxWidth = Number(arg.textMaxWidth) * progress
        }
        if (typeof arg?.letterSpace !== 'undefined' && letterSpace) {
          this.letterSpace = Number(arg.letterSpace) * progress
        }
        if (typeof arg?.fontSize !== 'undefined') {
          const baseFontSize = this['back_fontSize'] ?? 14
          this.fontSize = baseFontSize + (Number(arg.fontSize) - baseFontSize) * progress
        }

        if (typeof arg.fillStyle !== 'undefined') {
          const [rgbastr, rgba] = color.convertColorToRGBA(arg.fillStyle)
          const [s_rgbas, s_rgba] = color.convertColorToRGBA(this['back_fillStyle'])
          const rgbaResult = subtract(s_rgba, rgba, true)
          rgbaResult[0] = s_rgba[0] + progress * rgbaResult[0]
          rgbaResult[1] = s_rgba[1] + progress * rgbaResult[1]
          rgbaResult[2] = s_rgba[2] + progress * rgbaResult[2]
          rgbaResult[3] = s_rgba[3] + progress * rgbaResult[3]
          this.fillStyle = `rgba(${rgbaResult[0]},${rgbaResult[1]},${rgbaResult[2]},${rgbaResult[3]})`
        }
        if (typeof arg.strokeStyle !== 'undefined') {
          const [rgbastr, rgba] = color.convertColorToRGBA(arg.strokeStyle)
          const [s_rgbas, s_rgba] = color.convertColorToRGBA(this['back_strokeStyle'])
          const rgbaResult = subtract(s_rgba, rgba, true)
          rgbaResult[0] = s_rgba[0] + progress * rgbaResult[0]
          rgbaResult[1] = s_rgba[1] + progress * rgbaResult[1]
          rgbaResult[2] = s_rgba[2] + progress * rgbaResult[2]
          rgbaResult[3] = s_rgba[3] + progress * rgbaResult[3]
          this.strokeStyle = `rgba(${rgbaResult[0]},${rgbaResult[1]},${rgbaResult[2]},${rgbaResult[3]})`
        }
        this.x = x
        this.y = y
        this.width = width
        this.height = height
        this.canvas.draw()
      })
      .then(() => {
        this.playing = false
        return Promise.resolve(this)
      })
  }
}
